<?php
namespace plugins\appmarket\controller; //Demo插件英文名，改成你的插件英文就行了
use cmf\controller\PluginAdminBaseController;//引入此类
use think\Db;
use think\Validate;
use app\common\lib\AccessAuthorization;
use plugins\appmarket\controller\PublishController;
use think\Config;

/**
 * 模块审核控制器
 */
class AuditController extends PluginAdminBaseController
{
   	protected function _initialize()
    {
        parent::_initialize();
        $adminId = cmf_get_current_admin_id();
        //获取后台管理员id，可判断是否登录
        if (!empty($adminId)) {
            $this->assign("admin_id", $adminId);
        }
    }
    /**
     * 模块审核首页
     * @adminMenu(
     *     'name'   => '模块审核',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> true,
     *     'hasView'=> true,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '模块审核',
     *     'param'  => ''
     * )
     */
    public function index()
    {
		$param = $this->request->param();
		$search = [
			'search' => isset($param [ 'search' ]) ? $param['search'] : null,
			'step' => isset($param [ 'step' ]) ? $param['step'] : 100
		];
        //获取需要审核的数据 status = 1
        $list = Db::name('module_store')->where('status', 1)->field('id,name,title,describe,author,price,version,status,step');
		if( !empty( $search [ 'search' ] ) ){
			if( $search [ 'step' ] !== 100  ){
				$list = $list->where( 'step' , $search [ 'step' ] );
			}
		}
		$list = $list ->select()->toArray();
        foreach ($list as $key => $value) {
            $name = cmf_parse_name( $value ['name'] , 1 );
            $plugin = Db::name('plugin')->where( 'name' , $name )->find();
            $list [ $key ] ['installed'] = !empty($plugin) ? 1 : 0;
        }
		$this->assign( 'search' , $search );
        $this->assign( 'statusColor' , PublishController::$statusColor );
        $this->assign( 'statusStr' , PublishController::$statusStr );
        $this->assign( 'list' , $list );
        return $this->fetch();
    }

    /**
     * 模块通过
     * @adminMenu(
     *     'name'   => '申请通过',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '申请通过',
     *     'param'  => ''
     * )
     */
    public function pass( $id , $step )
    {   
        $status = ( $step == 1 ) ? 3 : 4 ;  // 3 进入第二步   4已通过
        $content = ( $step == 1 ) ? "流程一审核通过" : "流程二审核通过" ;
        //不论是第一步还是第二步，通过审核都是第二步
        $res = Db::name('module_store')->where( 'id' ,  $id )->update( ['status' => $status , 'step' => 2 ]);
        if( !$res ){
            return zy_json_echo( false , '操作失败，请稍后再试！');
        }
        //流程一通过需要添加菜单到 admin_menu
        if( $step == 1 ){
            $this->addAdminMenu( $id );
        }
        $log['module_id'] = $id;
        $log['content'] = '<span style="color:green;" class="glyphicon glyphicon-ok"></span>'.$content;
        //写入通过日志
        PublishController::addLog( $log );
        return zy_json_echo( true, '操作成功！' );
    }
    /**
     * 添加模块菜单到菜单库
     * $id module_store 的id
     */
    private function addAdminMenu( $id )
    {
        try {
            $module = Db::name( 'module_store' )->where( 'id' , $id )->find();
            $where = [
                'app' => 'admin' ,
                'controller' => 'Plugin',
                'action' => 'default'
            ];
            $parentId = Db::name( 'admin_menu' )->where( $where )->value('id');
            $app = 'plugin/'.$module['name'];

            $menu = [
                'parent_id' => $parentId,
                'type' => 0,
                'status' => 1,
                'list_order' => 1000,
                'app' => $app,
                'controller' => 'AdminIndex',
                'action' => 'index',
                'name' => $module['title'],
                'remark' => $module['title'],
            ];
            $find = Db::name( 'admin_menu' )->where( ['app' => $menu['app'] , 'controller' => 'AdminIndex' , 'action' => 'index' ] )->find();
            if( empty( $find ) ){
                $menu_id = Db::name('admin_menu')->insertGetId( $menu );
				//save menu_id
				Db::name( 'module_store' )->where( 'id' , $id )->update( [ 'menu_id' => $menu_id ] );
            }
        } catch ( \Exception $e) {
            $log['module_id'] = $id;
            $log['content'] = '<span style="color:orange;" class="glyphicon glyphicon-warning-sign"></span>通过审核，但是加入菜单的时候发生了某些异常，模块菜单未能顺利加入菜单库。';
            //写入通过日志
            PublishController::addLog( $log );
        }
    }

    /**
     * 申请拒绝页面
     * @return [type] [description]
     * @adminMenu(
     *     'name'   => '申请拒绝',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '申请拒绝',
     *     'param'  => ''
     * )
     */
    public function refuse()
    {
        return $this->fetch();
    }

    /**
     * 申请拒绝
     * @adminMenu(
     *     'name'   => '申请拒绝提交',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '申请拒绝提交',
     *     'param'  => ''
     * )
     */
    public function refusePost()
    {
        $data = $this->request->param();
        $id = $data ['id'];
        $content = $data['content'];
        $step = $data['step'];

        $log['module_id'] = $id;
        $log['content'] = '<div><span style="color:red;" class="glyphicon glyphicon-remove"></span>审核失败，拒绝理由：</div>'.$content;
        //写入拒绝日志
        PublishController::addLog( $log );
        $status = 2 ;  
        $res = Db::name('module_store')->where( 'id' ,  $id )->update( ['status' => $status ]);
        if( !$res ){
            return zy_json_echo( false , '操作失败，请稍后再试！');
        }
        return zy_json_echo( true, '拒绝申请操作成功！' );
    }

    /**
     * 查看详情
     * @adminMenu(
     *     'name'   => '模块详情',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> true,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '模块详情',
     *     'param'  => ''
     * )
     */
    public function particular( $id )
    {
        $publish = new PublishController();
        return $publish->particular( $id );
    }

    /**
     * 模块安装
     * 操作步骤：    1、下载源文件
     *              2、解压文件
     *              3、安装插件
     *@adminMenu(
     *     'name'   => '模块安装',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '模块安装',
     *     'param'  => ''
     * )
     */
    public function install( $id )
    {
        $downloadHost = Config( 'admin_module_config.download_host' );
        if( empty( $downloadHost ) ){
            return zy_json_echo( false , '未获取到主机地址！' );
        }
        //检查是否存在该模块文件，如果不存在就去下载并解压文件
        $pluginsPath = PLUGINS_PATH;
        $module = Db::name( 'module_store' )->where('id',$id)->find();

        if( empty( $module ) ) return zy_json_echo( false, '未找到模块信息！' );

		//针对审核时的安转，需要删除之前的模块信息再下在新的数据 
		
        $res = file_exists( $pluginsPath.DS.cmf_parse_name( $module['name'] ) ) ;
        if( $res == false ){
            //文件不存在，去下载并解压文件
            try {
                $url = $downloadHost.'/'.$module['resource'];
                $fileName = self::downloadFile( $url , cmf_parse_name( $module['name'] , 1 ) );
                self::unZip( $fileName );
				//删除安装包 
				$this->delDirAndFile($fileName);
            } catch (\Exception $e) {
                return zy_json_echo( false , $e->getMessage() );
            }
        }
		
        //执行安装操作
        $pluginInstallObj = new \app\admin\controller\PluginController();
		$pluginInstallObj->pluginModuleId = $id;
        $res = $pluginInstallObj -> install();
    }

    /**
     * 卸载模块
     * @adminMenu(
     *     'name'   => '模块卸载',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '模块卸载',
     *     'param'  => ''
     * )
     */
    public function unInstall ( )
    {
		$data = $this->request->param();
		$name = isset($data [ 'name' ] ) ? $data [ 'name' ] : '';
		
		$moduleId = Db::name('plugin')->where( 'name' , $name )->value( 'id' );
		if( empty($moduleId) ){
			$this->error('模块不存在,模块标识错误！');
		}
        //执行卸载操作
        $pluginInstallObj = new \app\admin\controller\PluginController();
        $res = $pluginInstallObj -> unInstall( $moduleId );
    }
	
	/**
	*删除模块元文件 
	*/
	public function unInstallDeleteFile( $id )
	{
		$module = Db::name( 'module_store' )->where('id',$id)->find();

        if( empty( $module ) ) return -1;
		$pluginsPath = PLUGINS_PATH;
		$path = $pluginsPath.DS.cmf_parse_name( $module['name'] );
		if( file_exists( $path ) ){
			$this->delDirAndFile( $path );
			return 0;
		}
	}
	
	//循环删除目录和文件函数 
	private function delDirAndFile( $dirName ) 
	{ 
		if( is_file($dirName) ){
			unlink($dirName);
			return true;
		}
		if ( $handle = opendir( "$dirName" ) ) { 
			while ( false !== ( $item = readdir( $handle ) ) ) { 
				if ( $item != "." && $item != ".." ) { 
					$itemPath = "$dirName/$item";
					//$itemPath = mb_convert_encoding ( "$dirName/$item" , 'gbk' , 'utf-8'  ); 
					if ( is_dir( $itemPath ) ) { 
						$this->delDirAndFile( $itemPath ); 
					} else { 
						if( unlink( $itemPath ) );
					} 
				} 
			} 
			closedir( $handle ); 
			if( rmdir( $dirName ) ) return true; 
		} 
	}


    /**
     * 解压文件
     */
    private static function unZip( $fileName )
    {   
		if( !file_exists( $fileName ) ){
			throw new \Exception( '文件包不存在！' );
		}
        $outPath = PLUGINS_PATH ;
        $zip = new \ZipArchive();
        try {
            $openRes = $zip->open( $fileName );
            if ($openRes === TRUE) {
              $zip->extractTo($outPath);
              $zip->close();
            }
        } catch (\Exception $e) {
            throw new \Exception( '解压异常：'.$e->getMessage() );
        }
        
    }

    /**
     *下载文件
     *$url 下载地址
     *$path 保存路径
     */
    private static function downloadFile( $url , $path )
    {
        $arr = parse_url( $url );
        $fileName = basename( $arr['path'] );
        try {
            $file = file_get_contents( $url );
        } catch (\Exception $e) {
            throw new \Exception('文件下载错误！');
        }
		$putPath = PLUGINS_PATH.$fileName;
        file_put_contents( $putPath , $file );
        return $putPath;
    }
	
	/**
     * 卸载模块
     * @adminMenu(
     *     'name'   => '清除',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 1000,
     *     'icon'   => '',
     *     'remark' => '清除',
     *     'param'  => ''
     * )
     */
	public function clear($name)
	{
		$name = cmf_parse_name( $name );
		//dump($name);exit;
		$rootPath = PLUGINS_PATH;
		
		$dir = $rootPath.DS.$name;
		if( file_exists ($dir) ){
			try{
				$this->delDirAndFile($dir);
			}catch( \Exception $e ){
				return zy_json_echo(false , '操作异常：'.$e->getMessage());
			}
			
			return zy_json_echo(true , '操作成功！');
		}else{
			return zy_json_echo(false , "未找到文件相关！");
		}
	
	}
	
	//检查安装包目录
	public function checkDir( $id )
	{
		$module = Db::name( 'module_store' )->where('id',$id)->find();
		//dump($module);
		$filename = ROOT_PATH.'public'.DS.$module['resource'];
		$filename = str_replace( '/' , DS , $filename );
		dump($filename);
		if( !file_exists( $filename ) ){
			return '资源文件不存在！' ;
		}
		$outPath = ROOT_PATH.'public/upload/checkmodulesource';

		if( !file_exists($outPath) ){
			mkdir( $outPath , 0777 );
		}
		
        $zip = new \ZipArchive();
        try {
            $openRes = $zip->open( $filename );
            if ($openRes === TRUE) {
              $zip->extractTo($outPath);
              $zip->close();
            }
        } catch (\Exception $e) {
            return  '解压异常：'.$e->getMessage() ;
        }
		
		$dir = $this->checkDirLevel( $outPath ) ;
		dump($dir);
		$this->assign( 'dir' , json_encode( $dir ) );
		return $this->fetch( 'check_dir' );
	}
	
	protected $id = 1;
	public function checkDirLevel( $filename , $level = 0 , $parent_id = 0 )
	{
		$list = [];
		$dir = scandir( $filename );
		foreach( $dir as $key => $value ){
			if( $value == '.' || $value == '..' ) continue;
			$v = [];
			$v ['text']	 = $value;
			$v [ 'level' ] = $level; 
			$v [ 'id' ] = $this->id;
			$v [ 'parent_id' ] = $parent_id;
			$this->id = $this->id + 1;
			if( is_dir( $filename.DS.$value ) && $level <= 2 ){
				$v [ 'nodes' ] = $this->checkDirLevel( $filename.DS.$value , $level++ , $v['id'] );
			}	
			$list [] = $v ;
		}
		return $list;		
	}
	

	
	
	
	

}